// for before c99
#ifndef __PROTOCOL_LIGHT_OPERATE_H__
#define __PROTOCOL_LIGHT_OPERATE_H__
#include <typeConvert.h>
#if LT_PTC_CMD_USE_CRYPTE
#include <sm4.h>
#endif
// protocol light
// protocol light length type
typedef uint16_t ltPtcLenType;

// protocol Parse Common state Enum
enum ltPtcPsStEnum
{
    ltPtcPsSt_Begin = 0, // begin to parse data
    ltPtcPsSt_FixHd,     // fixed head
    ltPtcPsSt_Vers,      // version
    ltPtcPsSt_Hd,        // version head
    ltPtcPsSt_Data,      // data
};
// protocol Parse version Enum
enum ltPtcPsVersEnum
{
    ltPtcPsVers0 = 0, // version 0
    ltPtcPsVers1,     // version 1
    ltPtcPsVers2,     // version 2
};
// PTC:protocol
#define LT_PTC_PACK_PST_BEG 0  // begin position
#define LT_PTC_PACK_PST_VERS 2 // version position
#define LT_PTC_PACK_PST_CRC 3  // data crc position
// VERSION 1
#define LT_PTC_V1_PST_SIZE 4   // version 1 size position
#define LT_PTC_V1_PST_ADDR 6   // version 1 addr position
#define LT_PTC_V1_PST_CRYPTE 7 // version 1 encrypte position
#define LT_PTC_V1_PST_CMDID 8  // version 1 command position
#define LT_PTC_V1_PST_RESP 10  // version 1 response position
#define LT_PTC_V1_PST_CRC1 11  // version 1 crc1 position
#define LT_PTC_V1_PST_DATA 12  // version 1 data position
// VERSION 2
// #define PTC_LT_V2_PST_SIZE 4     // version 2 size position
// #define PTC_LT_V2_PST_CRYPTE 8 // version 2 encrypte  position
// #define PTC_LT_V2_PST_CPRS 9 // version 2 compress position
// #define PTC_LT_V2_PST_RESERVE 10 // version 2 reserve position
// #define PTC_LT_V2_PST_DATA 12     // version 2 data position

// protocol Parse operate struct
typedef struct
{
#if LT_PTC_CMD_USE_CRYPTE
    char ltPtcKeyDlg[SM4_BLOCK_SIZE];
#endif
#if LT_PTC_CMD_HOST_ENABLE
    uint8_t hostSndInf[24];
#endif
    ltPtcLenType subRespSizeHostCmdId; // sub:response size; host:send cmd id
    uint8_t subRespCrypteHostAddr;     // sub:do cmd response crypte type; host:send addr.
    uint8_t subRespStatFlag;           // sub:do cmd response flag. host:deal response data result.
    ltPtcLenType totalsize;            // pkptr's size
    ltPtcLenType rcvCount;             // receive counter
    ltPtcLenType needSize;             // receive need size
    uint8_t parseState;                // parse state
    uint8_t ptcAddr;                   // reserve data, just for alignment.
    uint8_t pkptr[1];                  // pack buffer
} ltPtcParseStc;
#define ltPtcPsComSize (offsetof(ltPtcParseStc, pkptr))

#define ltPtcStcPtr(ptcPtr) ((ltPtcParseStc *)ptcPtr)

#define ltPtcGetMyaddr(ptcPtr) (ltPtcStcPtr(ptcPtr)->ptcAddr)
#define ltPtcSetMyaddr(ptcPtr, smyaddr) (ltPtcStcPtr(ptcPtr)->ptcAddr = smyaddr)
#if LT_PTC_CMD_USE_CRYPTE
#define ltPtcGetKeyDlgPtr(ptcPtr) (ltPtcStcPtr(ptcPtr)->ltPtcKeyDlg)
#endif

#define ltPtcGetPackPtr(ptcPtr) (ltPtcStcPtr(ptcPtr)->pkptr)

#define ltPtcGetVers(ptcPtr) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_PACK_PST_VERS])
#define ltPtcSetVers(ptcPtr, svers) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_PACK_PST_VERS] = svers)

#define ltPtcGetCrc(ptcPtr) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_PACK_PST_CRC])
#define ltPtcSetCrc(ptcPtr, scrc) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_PACK_PST_CRC] = scrc)

#define ltPtcGetDataSizeV1(ptcPtr) (ovtBigSys16(*((uint16_t *)(&ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_SIZE]))))
#define ltPtcSetDataSizeV1(ptcPtr, ssize) (*((uint16_t *)(&ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_SIZE])) = ovtBigSys16(ssize))

#define ltPtcGetHeadSizeV1 (LT_PTC_V1_PST_DATA)
#define ltPtcGetPackSizeV1(ptcPtr) (ltPtcGetHeadSizeV1 + ltPtcGetDataSizeV1(ptcPtr))
#define ltPtcGetDataMaxSizeV1(ptcPtr) (ltPtcStcPtr(ptcPtr)->totalsize - ltPtcGetHeadSizeV1)

#define ltPtcGetAddrV1(ptcPtr) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_ADDR])
#define ltPtcSetAddrV1(ptcPtr, saddr) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_ADDR] = saddr)

#define ltPtcGetCrypteV1(ptcPtr) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_CRYPTE])
#define ltPtcSetCrypteV1(ptcPtr, scrp) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_CRYPTE] = scrp)

#define ltPtcGetCmdIdV1(ptcPtr) (ovtBigSys16(*((uint16_t *)(&ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_CMDID]))))
#define ltPtcSetCmdIdV1(ptcPtr, sid) (*((uint16_t *)(&ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_CMDID])) = ovtBigSys16(sid))

#define ltPtcGetResponseV1(ptcPtr) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_RESP])
#define ltPtcSetResponseV1(ptcPtr, sresp) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_RESP] = sresp)

#define ltPtcGetCrc1V1(ptcPtr) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_CRC1])
#define ltPtcSetCrc1V1(ptcPtr, sresp) (ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_CRC1] = sresp)

#define ltPtcGetDataPtrV1(ptcPtr) (&ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_DATA])
#define ltPtcSetDataV1(ptcPtr, sbuf, ssize) (memcpypro(&ltPtcStcPtr(ptcPtr)->pkptr[LT_PTC_V1_PST_DATA], ltPtcGetDataMaxSizeV1(ptcPtr), \
                                                       sbuf, ssize),                                                                   \
                                             ltPtcSetDataSizeV1(ptcPtr, ssize))

ltPtcLenType ltPtcPackFinV1(void *ptcPtr);
int ltPtcInitV1(void *ptcPtr, ltPtcLenType setPackSize);
int ltPtcPsDataV1(void *ptcPtr, uint8_t indata);

// cmd struct name define
#define ltCmdStciDef(sname) ltCmdStci_##sname
#define ltCmdStcoDef(sname) ltCmdStco_##sname
#define ltCmdUnionDef(sname) ltCmdUnion_##sname
// cmd enum name define
#define ltCmdEnumDef(sname) ltCmdEnum_##sname
// cmd input overturn function
#define ltCmdFunOvtiDef(sname) ltCmdFunOvti_##sname
// cmd out overturn function
#define ltCmdFunOvtoDef(sname) ltCmdFunOvto_##sname
#if LT_PTC_CMD_SUB_ENABLE
// cmd business function
#define ltCmdFunSubDoDef(sname) ltSubDoCmdFun_##sname
int ltPtcSubPsAndDeal(void *inptr, char indata);
#endif
#if LT_PTC_CMD_HOST_ENABLE
// cmd master pack command function
#define ltCmdFunHostPackDef(sname) ltHostPackFun_##sname
#define ltCmdFunHostDealDef(sname) ltHostDoRespFun_##sname
// set data can use ltPtcGetDataPtrV1
int ltPtcHostPackCommV1(void *inptr, uint8_t saddr, uint8_t scrypte, uint16_t cmdid, ltPtcLenType cmdlen);
int ltPtcHostPsAndDeal(void *inptr, char indata);
#endif

enum ltCmdRespEnum
{
    ltPtcCmdResp_OK = 0,
    ltPtcCmdResp_NotSndBack, // this response used to not response command.
    ltPtcCmdResp_NdCrypt,// need crypte
    ltPtcCmdResp_SnErr,// SN error
    ltPtcCmdResp_KeyErr,// 
    ltPtcCmdResp_CryptErr,
    ltPtcCmdResp_CryptCrcErr,
    ltPtcCmdResp_LenErr,
};
// protocol Parse crypte Enum
enum ltPtcCrpEnum
{
    ltPtcCrypte_None = 0,
    ltPtcCrypte_AesPre, // present key
    ltPtcCrypte_AesDlg, // dialogue key
    ltPtcCrypte_Rsa,
    ltPtcCrypte_Sm4Pre, // present key
    ltPtcCrypte_Sm4Dlg, // dialogue key
    ltPtcCrypte_Sm2,
    ltPtcCrypte_Des3Pre, // present key
    ltPtcCrypte_Des3Dlg, // dialogue key
    //
};
#endif